<?php

namespace addons\third\library;

use addons\third\model\Third;
use app\common\model\User;
use app\common\model\Wxuser;
use fast\Random;
use think\Db;
// use think\Exception;
use think\exception\PDOException;
use think\Log;
use app\common\model\UserAudit;
use app\common\library\Exception;
use app\common\library\Wemini as WeminiLibrary;
use app\common\model\ActiveInfo;
use app\common\model\UserCard;

/**
 * 第三方登录服务类
 *
 * @author Karson
 */
class Service
{

    public $auth = null;
    public $User = null;
    public $Wxuser = null;
    public $Third = null;

    /**
     * 第三方登录
     * @param string $platform 平台
     * @param array  $params   参数
     * @param array  $extend   会员扩展信息
     * @param int    $keeptime 有效时长
     * @return boolean
     */
    public static function connect($platform, $params = [], $extend = [], $keeptime = 0)
    {
        if (!empty($params['userinfo']['nickname']) && !empty($params['userinfo'])) {
            $params['userinfo']['nickname'] = self::removeEmoji($params['userinfo']['nickname']);
        }

        \think\Log::record('connect####$params###');
        \think\Log::record($params);

        $time = time();
        $values = [
            'platform'      => $platform,
            'openid'        => $params['openid'],
            'openname'      => isset($params['userinfo']['nickname']) ? $params['userinfo']['nickname'] : '',
            'access_token'  => $params['access_token'],
            'refresh_token' => $params['refresh_token'],
            'expires_in'    => $params['expires_in'],
            'logintime'     => $time,
            'expiretime'    => $time + $params['expires_in'],
        ];
        $auth = \app\common\library\Auth::instance();

        Db::startTrans();
        try {
            $auth->keeptime($keeptime);
            $third = Third::get(['platform' => $platform, 'openid' => $params['openid']]);
            if ($third) {
                $third->save($values);
            } else {
                $third = Third::create($values);
            }

            $wxuser = [
                'subscribe'         => isset($params['subscribe']) ? $params['subscribe'] : 0,
                'subscribe_time'    => isset($params['subscribe_time']) ? $params['subscribe_time'] : 0
            ];
            if (!empty($params['userinfo'])) {
                $wxuser['nickname']     = $params['userinfo']['nickname'];
                $wxuser['sex']          = $params['userinfo']['sex'];
                $wxuser['city']         = $params['userinfo']['city'];
                $wxuser['country']      = $params['userinfo']['country'];
                $wxuser['province']     = $params['userinfo']['province'];
                $wxuser['headimgurl']   = $params['userinfo']['headimgurl'];
            }

            $wxuserInfo = model('Wxuser')->where('openid', $params['openid'])->where('store_id', $auth->getStoreId())->find();
            if (!$wxuserInfo) {
                $user = self::register($params, $extend, $keeptime);
                // wxuserinfo 保存
                $wxuser['uid'] = $user->id;
                $wxuser['store_id'] = $auth->getStoreId();
                $wxuser['openid'] = $params['openid'];
                $wxuser['createtime']   = time();
                Wxuser::create($wxuser);
            } else {
                if ($wxuserInfo['uid'] <= 0) {
                    $user = self::register($params, $extend, $keeptime);
                    $wxuser['uid'] = $user['id'];
                    $wxuserInfo->save($wxuser);
                } else {
                    $user = model('User')->where('id', $wxuserInfo['uid'])->where('store_id', $auth->getStoreId())->find();
                    if (!$user) {
                        $user = self::register($params, $extend, $keeptime);
                        $wxuser['uid'] = $user->id;
                        $wxuserInfo->save($wxuser);
                    } else {
                        if (empty($user->avatar) && isset($params['userinfo']['avatar'])) {
                            $user->avatar = $params['userinfo']['avatar'];
                            $user->save();
                        }
                    }
                }
            }
            Db::commit();
        } catch (PDOException $e) {
            Db::rollback();
            $auth->logout();
            // TODO: 调试生产环境错误，调试完成后还原
            Log::record($e->getMessage(), Log::ERROR);
            new Exception($e->getMessage());
        }

        // 写入登录Cookies和Token
        return $auth->direct($user->id);
    }
    /**
     * 登录
     * @param string $result
     * @return boolean
     */
    public function new_connect($platform, $params, $extend)
    {

        $this->auth = \app\common\library\Auth::instance();
        \think\Log::record('$params');
        \think\Log::record($params);
        $third = Third::get(['platform' => $platform, 'openid' => $params['openid']]);

        \think\Log::record('new_connect####$params###');
        \think\Log::record($params);

        // 之前未注册
        if (empty($third)) {
            $this->User = new User();
            $this->Wxuser = new Wxuser();
            $this->Third = new Third();

            \think\Log::record('$params###' . json_encode($params));

            // 获取SESSION KEY的数据
            $WeminiLibrary = new WeminiLibrary();
            $sessionKey = $WeminiLibrary->getSessionKey();
            \think\Log::record('$sessionKey##' . json_encode($sessionKey));

            // 如果没有unionid,返回提示.
            if (empty($params['unionId'])) {
                $params['unionId'] = $params['openid'];
                // TODO:测试用，先这样
                // new Exception('get unionid fail, login fail.');
            }

            $params['unionid'] = $params['unionId'];

            // 获取分会ID
            $stroeID = $this->auth->getStoreId();

            // 微信小程序
            if ($platform == Wxuser::PLATFORM_WEMINI) {
                return $this->weminiLoginRegister($platform, $stroeID, $params, $extend);
                // 微信公众号
            } else if ($platform == Wxuser::PLATFORM_WECHAT) {
                return $this->wechatLoginRegister($platform, $stroeID, $params, $extend);
            }

            // 注册过
        } else {
            // 直接登录
            return $this->auth->direct($third['user_id']);
        }
    }


    /**
     * 公众号登录注册
     * 
     * @param string    $platform   平台
     * @param int       $stroeID    分会ID
     * @param array     $wechatData 微信数据
     * @param array     $extend     额外的参数
     * @param int       $keeptime   有效时长
     * @return array
     */
    public function wechatLoginRegister($platform, $stroeID, $wechatData, $extend = [], $keeptime = 0)
    {
        if (empty($platform) || empty($stroeID) || empty($wechatData)) {
            new Exception('Params error');
        }

        // 通过unionid判断用户是否通过小程序注册过用户
        $where = [
            'platform' => Wxuser::PLATFORM_WEMINI,
            'unionid' => $wechatData['unionid']
        ];
        $userID = $this->Wxuser->where($where)->value('uid');

        $time = time();

        if (empty($userID)) { // 之前未使用小程序注册过

            // 注册公众号用户
            // 创建用户(user表)
            $userData = self::register($wechatData, $extend, $keeptime);

            // 创建一条第三方登录记录(third表)
            $this->Third->createThird($platform, $userData['id'], $userData['mobile'], $wechatData, $time);

            // 校验该微信用户是否已经存在公众号微信用户的数据
            $where = [
                'platform' => Wxuser::PLATFORM_WECHAT,
                'unionid' => $wechatData['unionid']
            ];
            $wxuserID = $this->Wxuser->where($where)->value('id');

            if (empty($wxuserID)) {
                // 创建微信用户(wxuser表)
                $this->Wxuser->createWechatUser($platform, $stroeID, $userData['id'], $wechatData);
            } else {
                // 更新微信用户(wxuser表)
                $this->Wxuser->updateWechatUser($wxuserID, $platform, $stroeID, $userData['id'], $wechatData);
            }


            // 同步用户名片
            $UserCard = new UserCard();
            $UserCard->synchronizationUserCard($userData['id']);

            // 直接登录
            return $this->auth->direct($userData['id']);
        } else { // 之前有使用小程序注册过

            // 绑定已有的账号
            $mobile = $this->User->where('id', $userID)->value('mobile');

            // 创建一条第三方登录记录(third表)
            $this->Third->createThird($platform, $userID, $mobile, $wechatData, $time);


            // 校验该微信用户是否已经存在公众号微信用户的数据
            $where = [
                'platform' => Wxuser::PLATFORM_WECHAT,
                'unionid' => $wechatData['unionid']
            ];
            $wxuserID = $this->Wxuser->where($where)->value('id');

            if (empty($wxuserID)) {
                // 创建微信用户(wxuser表)
                $this->Wxuser->createWechatUser($platform, $stroeID, $userID, $wechatData);
            } else {
                // 更新微信用户(wxuser表)
                $this->Wxuser->updateWechatUser($wxuserID, $platform, $stroeID, $userID, $wechatData);
            }

            // 同步用户名片
            $UserCard = new UserCard();
            $UserCard->synchronizationUserCard($userID);

            // 直接登录
            return $this->auth->direct($userID);
        }
    }


    /**
     * 小程序登录注册
     * 
     * @param string    $platform   平台
     * @param int       $stroeID    分会ID
     * @param array     $wechatData 微信数据
     * @param array     $extend     额外的参数
     * @param int       $keeptime   有效时长
     * @return array
     */
    public function weminiLoginRegister($platform, $stroeID, $wechatData, $extend = [], $keeptime = 0)
    {
        if (empty($platform) || empty($stroeID) || empty($wechatData)) {
            new Exception('Params error');
        }

        \think\Log::record('#wechatData##' . json_encode($wechatData));
        // 通过unionid判断用户是否通过公众号注册过用户
        $where = [
            'platform' => Wxuser::PLATFORM_WECHAT,
            'unionid' => $wechatData['unionid']
        ];
        $wxuserData = $this->Wxuser->where($where)->find();
        $userID = $wxuserData['uid'];

        $time = time();

        $Wemini = new WeminiLibrary();
        $this->User = new User();
        $this->Wxuser = new Wxuser();
        $this->Third = new Third();

        if (empty($userID)) { // 未使用微信公众号注册过
            // 解密手机号码
            $phoneData = $Wemini->decryptDataGetPhone(
                $stroeID,
                $wechatData['encryptedData'],
                $wechatData['iv']
            );
            $result['purePhoneNumber'] = $phoneData['purePhoneNumber'];

            // 校验该手机号码是否已绑定账号
            $userData = $this->User->where('mobile', $phoneData['purePhoneNumber'])->find();

            if (empty($userData)) { // 该手机号码之前未绑定账号

                // 注册小程序用户并绑定手机号
                // 创建用户(user表)
                $extend['mobile'] = $phoneData['purePhoneNumber'];
                $userData = self::register($wechatData, $extend, $keeptime);

                // 创建一条第三方登录记录(third表)
                $this->Third->createThird($platform, $userData['id'], $userData['mobile'], $wechatData, $time);

                // 创建微信用户(wxuser表)
                $this->Wxuser->createWechatUser($platform, $stroeID, $userData['id'], $wechatData);

                // 验证当前手机号码之前是否替会员参加过活动
                $ActiveInfo = new ActiveInfo();
                $where = [
                    'replace_mobile' => $userData['mobile']
                ];
                $count = $ActiveInfo->where($where)->count('*');

                // 之前有替会员参加过活动
                if (!empty($count)) {
                    // 更新替代人UID
                    $updateData = [
                        'replace_uid' => $userData['id']
                    ];
                    $ActiveInfo->where($where)->update($updateData);
                }
            } else { // 该手机号之前已经绑定其他账号

                // 绑定已有的账号

                // 创建一条第三方登录记录(third表)
                $this->Third->createThird($platform, $userData['id'], $userData['mobile'], $wechatData, $time);

                // 创建微信用户(wxuser表)
                $this->Wxuser->createWechatUser($platform, $stroeID, $userData['id'], $wechatData);
            }

            // 如果存在微信公众号的微信用户信息 且 还没有绑定用户(走到这里说明已经可以确认没有绑定用户了)
            if (!empty($wxuserData)) {
                // 绑定
                $this->Wxuser->where('id', $wxuserData['id'])->update([
                    'uid' => $userData['id']
                ]);
            }

            // 同步用户名片
            $UserCard = new UserCard();
            $UserCard->synchronizationUserCard($userData['id']);

            // 登录
            return $this->auth->direct($userData['id']);
        } else { // 之前已经使用微信公众号注册过
            // 获取用户信息
            $mobile = $this->User->where('id', $userID)->value('mobile');
            // 验证是否绑定手机号码
            if (empty($mobile)) { // 未绑定

                // 解密手机号码
                $phoneData = $Wemini->decryptDataGetPhone(
                    $stroeID,
                    $wechatData['encryptedData'],
                    $wechatData['iv']
                );
                $mobile = $phoneData['purePhoneNumber'];
            }

            // 创建一条第三方登录记录(third表)
            $this->Third->createThird($platform, $userID, $mobile, $wechatData, $time);

            // 创建微信用户(wxuser表)
            $this->Wxuser->createWechatUser($platform, $stroeID, $userID, $wechatData);

            // 同步用户名片
            $UserCard = new UserCard();
            $UserCard->synchronizationUserCard($userID);

            // 直接登录
            return $this->auth->direct($userID);
        }
    }








    /**
     * 公众号和小程序统一注册
     * @param string $result
     * @return boolean
     */
    public static function UnifiedRegister($platform, $params = [], $extend = [], $keeptime = 0)
    {
        if (!empty($params['userinfo']['nickname']) && !empty($params['userinfo'])) {
            $params['userinfo']['nickname'] = self::removeEmoji($params['userinfo']['nickname']);
        }
        $values = [
            'platform'      => $platform,
            'openid'        => $params['userinfo']['openid'],
            'openname'      => isset($params['userinfo']['nickname']) ? $params['userinfo']['nickname'] : '',
        ];
        $auth = \app\common\library\Auth::instance();

        Db::startTrans();
        try {
            $auth->keeptime($keeptime);
            $third = Third::get(['platform' => $platform, 'openid' => $params['userinfo']['openid']]);
            if ($third) {
                $third->save($values);
            } else {
                $third = Third::create($values);
            }

            $wxuser = [
                'subscribe'         => isset($params['subscribe']) ? $params['subscribe'] : 0,
                'subscribe_time'    => isset($params['subscribe_time']) ? $params['subscribe_time'] : 0,
                'platform'          => $platform
            ];
            if (!empty($params['userinfo'])) {
                $wxuser['nickname']     = $params['userinfo']['nickname'];
                $wxuser['sex']          = $params['userinfo']['sex'];
                $wxuser['city']         = $params['userinfo']['city'];
                $wxuser['country']      = $params['userinfo']['country'];
                $wxuser['province']     = $params['userinfo']['province'];
                $wxuser['headimgurl']   = $params['userinfo']['avatar'];
            }

            $wxuserInfo = model('Wxuser')->where('openid', $params['userinfo']['openid'])->where('platform', $platform)->where('store_id', $auth->getStoreId())->find();
            if (!$wxuserInfo) {
                $user = model('User')->where(['mobile' => $params['mobile'], 'store_id' => $auth->getStoreId()])->find();
                if (!$user) {
                    $user = self::register($params, $extend, $keeptime);
                }
                // wxuserinfo 保存
                $wxuser['uid'] = $user->id;
                $wxuser['store_id'] = $auth->getStoreId();
                $wxuser['openid'] = $params['userinfo']['openid'];
                $wxuser['createtime']   = time();
                Wxuser::create($wxuser);
            } else {
                if ($wxuserInfo['uid'] <= 0) {
                    $user = model('User')->where(['mobile' => $params['mobile'], 'store_id' => $auth->getStoreId()])->find();
                    if (!$user) {
                        $user = self::register($params, $extend, $keeptime);
                    }
                    $wxuser['uid'] = $user['id'];
                    $wxuserInfo->save($wxuser);
                } else {
                    $user = model('User')->where('id', $wxuserInfo['uid'])->where('store_id', $auth->getStoreId())->find();
                    if (!$user) {
                        $user = model('User')->where(['mobile' => $params['mobile'], 'store_id' => $auth->getStoreId()])->find();
                        if (!$user) {
                            $user = self::register($params, $extend, $keeptime);
                        }
                        $wxuser['uid'] = $user->id;
                        $wxuserInfo->save($wxuser);
                    } else {
                        if (empty($user->avatar) && isset($params['userinfo']['avatar'])) {
                            $user->avatar = $params['userinfo']['avatar'];
                            $user->save();
                        }
                    }
                }
            }


            if ($params['register_type'] == User::REGISTER_TYPE_MEMBER) {
                $autidInfo = model('UserAudit')->where('mobile', $params['mobile'])->where('status', UserAudit::STATUS_AUDIT_INREVIEW)->where('store_id', $auth->getStoreId())->find();
                if (!$autidInfo) {
                    $is_insert = UserAudit::create([
                        'uid'       => $user->id,
                        'store_id'  => $auth->getStoreId(),
                        'status'    => UserAudit::STATUS_AUDIT_INREVIEW,
                        'mobile'    => $params['mobile'],
                        'nickname'  => $params['name'],
                        'industry'  => $params['industry'],
                        'sign_photo' => $params['sign_photo'],
                    ]);
                    if (!$is_insert) {
                        Db::rollback();
                        new Exception('注册失败');
                    }
                }
            }
            Db::commit();
        } catch (PDOException $e) {
            Db::rollback();
            $auth->logout();
            // TODO: 调试生产环境错误，调试完成后还原
            Log::record($e->getMessage(), Log::ERROR);
            new Exception($e->getMessage());
        }

        // 写入登录Cookies和Token
        return $auth->direct($user->id);
    }

    /**
     * 注册用户(user表)
     * 
     * @param array $params     参数
     * @param array $extend     扩展参数
     * @param int   $keeptime   
     */
    static protected function register($params, $extend, $keeptime)
    {
        // 先随机一个用户名,随后再变更为u+数字id
        $username = Random::alnum(20);
        $password = Random::alnum(6);
        $domain = request()->host();

        $auth = \app\common\library\Auth::instance();
        // 默认注册一个会员
        $result = $auth->register($username, $password, $username . '@' . $domain, '', $extend, $keeptime);
        if (!$result) {
            throw new \Exception('注册失败！');
        }

        $user = $auth->getUser();
        $fields = ['username' => 'u' . $user->id, 'email' => 'u' . $user->id . '@' . $domain,'gender' => $params['userinfo']['sex']];
        if (isset($params['userinfo']['nickname'])) {
            $fields['nickname'] = $params['userinfo']['nickname'];
        }
        if (isset($params['userinfo']['avatar'])) {
            $fields['avatar'] = htmlspecialchars(strip_tags($params['userinfo']['avatar']));
            $fields['sign_photo'] = htmlspecialchars(strip_tags($params['userinfo']['avatar']));
        }

        // 更新会员资料
        $user = User::get($user->id);
        $user->save($fields);

        return $user;
    }

    static protected function removeEmoji($nickname)
    {
        return remove_emoji($nickname);
    }
}
